﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.Data;
using CPPEI.Coolzon.Data.MainServiceData;
using CPPEI.Coolzon.Server.CacheData;
using CPPEI.Coolzon.Service.Contract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.Coolzon.Server.ServiceImplement
{
    public class ReqCreateDomainHandler: BaseHandler<ReqCreateDomainData, RespCreateDomainData>
    {
        public ReqCreateDomainHandler()
            : base(Service.Contract.REQUEST_SCENARIO.CONNENT, Service.Contract.REQUEST_COMMAND.CONNECT.CREATEDOMAIN)
        {
        }

        protected override RespCreateDomainData OnHandle(Data.MainServiceData.Request request, ReqCreateDomainData requestData)
        {
            if (ServerData.IsUpdatingSolution)
            {
                Logger.InfoToTag("MainService", "终端{0}请求创建控制域{1},方案:{2},但方案正在更新中,创建失败", request.Header.UserIdentity, requestData.DomainCaption, requestData.SolutionName);
                return null;
            }
            Logger.InfoToTag("MainService", "终端{0}请求创建控制域{1},方案:{2}", request.Header.UserIdentity, requestData.DomainCaption, requestData.SolutionName);
            RespCreateDomainData result = new RespCreateDomainData();
            CacheData.Client client = ServerData.Instance.GetClient(request.Header.UserIdentity);
            if (client == null)
            {
                Logger.ErrorToTag("MainService", string.Format("用户:{0}创建域:{1}失败，用户不存在！", request.Header.UserIdentity, requestData.DomainCaption));
                result.IsSuccess = false;
                result.Message = "用户不存在";
                return result;
            }

            // 获取用户所要创建的域的方案的，域实例模型
            Settings.DomainInstanceMode domainInstanceMode = Settings.DomainInstanceMode.Singleton;

            if (domainInstanceMode == Settings.DomainInstanceMode.Singleton)
            {
                CreateDomain.SingletonModeCreateDomainStrategy strategy = new CreateDomain.SingletonModeCreateDomainStrategy();

                result = strategy.CreateDomain(request, requestData, client);
                return result;
            }
            else
            {
                #region // 多个域模式，允许创建控制域

                string domainId = string.Format("domain-{0}-{1}", requestData.SolutionName, request.Header.UserIdentity);
                CacheData.ControlDomain controldomain = ServerData.Instance.GetDomain(domainId);

                if (controldomain == null)
                {
                    controldomain = new CacheData.ControlDomain()
                    {
                        Id = string.Format("domain-{0}-{1}", requestData.SolutionName, request.Header.UserIdentity),
                        SolutionCaption = requestData.SolutionCaption,
                        SolutionName = requestData.SolutionName,
                        Caption = requestData.DomainCaption,
                        CreatorAccount = client.UserAccount,
                        CreatorName = client.UserAccount
                    };

                    if (ServerData.Instance.CreateDomain(controldomain))
                    {
                        #region // 将用户分配到控制域中
                        controldomain.AddClient(client);
                        client.State = ClientState.InDomain;
                        #endregion

                        #region // 判断是否是控制端
                        if (client.AppType.ToUpper() == "CONSOLEAPP")
                        {
                            // 判断域里是否有操作员
                            if (!controldomain.ValidateOperator())
                            {
                                // 设置为操作员
                                controldomain.SetOperator(client);
                            }
                        }
                        #endregion

                        result.IsSuccess = true;
                        result.Message = "创建成功";
                        result.IsNewDomain = true;
                        result.DomainId = controldomain.Id;
                        result.DomainCaption = controldomain.Caption;
                        result.OperatorIdentity = controldomain.OperatorIdentity;
                        Logger.InfoToTag("MainService", string.Format("用户{0}创建域{1}成功,DomainId:{2}！", request.Header.UserIdentity, requestData.DomainCaption, controldomain.Id));

                        // 通知其他用户加入控制域
                        NotifyDisplayClientEnter(request, controldomain);

                        return result;
                    }
                    else
                    {
                        result.IsSuccess = false;
                        result.Message = "域已达最大值";
                        Logger.WarningToTag("MainService", string.Format("用户{0}创建域{1}失败,域已达最大值！", request.Header.UserIdentity, requestData.DomainCaption));
                        return result;
                    }
                }
                else
                {
                    // 域已存在更新域里的控制端
                    controldomain.UpdateClient(client.UserIdentity, client);
                    client.State = ClientState.InDomain;

                    #region // 判断是否是控制端
                    if (client.AppType.ToUpper() == "CONSOLEAPP")
                    {
                        // 判断域里是否有操作员
                        if (!controldomain.ValidateOperator())
                        {
                            // 设置为操作员
                            controldomain.SetOperator(client);
                        }
                    }
                    #endregion

                    result.IsSuccess = true;
                    result.Message = "创建成功";
                    result.IsNewDomain = false;
                    result.DomainId = controldomain.Id;
                    result.DomainCaption = controldomain.Caption;
                    result.OperatorIdentity = controldomain.OperatorIdentity;
                    Logger.InfoToTag("MainService", string.Format("用户{0}创建域{1}成功,域已经存在DomainId:{2}！", request.Header.UserIdentity, requestData.DomainCaption, controldomain.Id));

                    // 通知其他用户加入控制域
                    NotifyDisplayClientEnter(request, controldomain);

                    return result;
                }
                #endregion
            }
        }

        /// <summary>
        /// 通知其他处于等待状态的展示端进入
        /// </summary>
        private void NotifyDisplayClientEnter(Data.MainServiceData.Request request, CPPEI.Coolzon.Server.CacheData.ControlDomain domain)
        {
            CacheData.Client[] clientList = CacheData.ServerData.Instance.GetClientList();

            // 通知各个客户端场景事件
            for (int index = 0; index < clientList.Length; index++)
            {
                CacheData.Client client = clientList[index];
                if (client!= null 
                    && client.Callback != null 
                    && client.State == ClientState.Waiting)
                {
                    domain.AddClient(client);

                    // 创建控制域时拉入到域的用户不需要同步视图状态，不需要中间状态
                    client.State = ClientState.InDomain;

                    Service.Contract.RespEnterDomainData enterDomainResponseData = new Service.Contract.RespEnterDomainData();
                    enterDomainResponseData.IsSuccess = true;
                    enterDomainResponseData.Message = "控制端拉入控制域";
                    enterDomainResponseData.SolutionName = domain.SolutionName;
                    enterDomainResponseData.SolutionCaption = domain.SolutionCaption;
                    enterDomainResponseData.DomainId = domain.Id;
                    enterDomainResponseData.DomainCaption = domain.Caption;
                    enterDomainResponseData.OperatorIdentity = domain.OperatorIdentity;
                    enterDomainResponseData.ViewStateAge = domain.ViewStateAge;
                    enterDomainResponseData.ViewStateToken = domain.ViewStateToken;
                    enterDomainResponseData.ViewStateSolution = domain.SolutionName;

                    Response response = new Response();
                    response.Header = new ResponseHeader();
                    response.Data = SerializeUtility.SerializeToBinary(enterDomainResponseData);
                    response.Header.Scenario = Service.Contract.RESPONSE_SCENARIO.CONNENT;
                    response.Header.Command = Service.Contract.RESPONSE_COMMAND.CONNECT.ENTERDOMAIN;
                    response.Header.SendTicks = DateTime.Now.Ticks;
                    response.Header.DataLength = response.Data.Length;
                    response.Header.RequestHeader = request.Header;
                    try
                    {
                        client.Callback.OnReceiveResponse(response);
                    }
                    catch(Exception ex)
                    {
                        Common.Logger.ErrorToTag("MainService", "通知用户{0}进入控制域{1}失败:{2}",
                            client.UserIdentity,
                            domain.Id,
                            ex);
                        client.Callback = null;
                    }
                }
            }
        }
    }
}
